r"""
Dedekind Domains
"""
# ****************************************************************************
#  Distributed under the terms of the GNU General Public License (GPL)
#                  https://www.gnu.org/licenses/
# *****************************************************************************
from sage.categories.category import Category
from sage.categories.integral_domains import IntegralDomains


class DedekindDomains(Category):
    """
    The category of Dedekind domains.

    A Dedekind domain is a Noetherian integral domain of Krull
    dimension one that is integrally closed in its field of fractions.

    EXAMPLES::

        sage: C = DedekindDomains(); C
        Category of Dedekind domains
        sage: C.super_categories()
        [Category of integral domains]

    TESTS::

        sage: TestSuite(C).run()
    """
    def super_categories(self):
        """
        EXAMPLES::

            sage: DedekindDomains().super_categories()
            [Category of integral domains]
        """
        return [IntegralDomains()]

    class ParentMethods:
        def krull_dimension(self):
            """
            Return 1 since Dedekind domains have Krull dimension 1.

            EXAMPLES:

            The following are examples of Dedekind domains::

                sage: ZZ.krull_dimension()
                1
                sage: x = polygen(ZZ, 'x')
                sage: K = NumberField(x^2 + 1, 's')                                         # needs sage.rings.number_field
                sage: OK = K.ring_of_integers()                                             # needs sage.rings.number_field
                sage: OK.krull_dimension()                                                  # needs sage.rings.number_field
                1

            The following are not Dedekind domains but have
            a ``krull_dimension`` function::

                sage: QQ.krull_dimension()
                0
                sage: T.<x,y> = PolynomialRing(QQ,2); T
                Multivariate Polynomial Ring in x, y over Rational Field
                sage: T.krull_dimension()
                2
                sage: U.<x,y,z> = PolynomialRing(ZZ,3); U
                Multivariate Polynomial Ring in x, y, z over Integer Ring
                sage: U.krull_dimension()
                4

                sage: # needs sage.rings.number_field
                sage: K.<i> = QuadraticField(-1)
                sage: R = K.order(2*i); R
                Order of conductor 2 generated by 2*i
                 in Number Field in i with defining polynomial x^2 + 1 with i = 1*I
                sage: R.is_maximal()
                False
                sage: R.krull_dimension()
                1
            """
            from sage.rings.integer_ring import ZZ
            return ZZ.one()

        def is_integrally_closed(self) -> bool:
            """
            Return ``True`` since Dedekind domains are integrally closed.

            EXAMPLES:

            The following are examples of Dedekind domains::

                sage: ZZ.is_integrally_closed()
                True
                sage: x = polygen(ZZ, 'x')
                sage: K = NumberField(x^2 + 1, 's')                                         # needs sage.rings.number_field
                sage: OK = K.ring_of_integers()                                             # needs sage.rings.number_field
                sage: OK.is_integrally_closed()                                             # needs sage.rings.number_field
                True

            These, however, are not Dedekind domains::

                sage: QQ.is_integrally_closed()
                True
                sage: S = ZZ[sqrt(5)]; S.is_integrally_closed()                             # needs sage.rings.number_field sage.symbolic
                False
                sage: T.<x,y> = PolynomialRing(QQ, 2); T
                Multivariate Polynomial Ring in x, y over Rational Field
                sage: T.is_integral_domain()
                True
            """
            return True

        def integral_closure(self):
            r"""
            Return ``self`` since Dedekind domains are integrally closed.

            EXAMPLES::

                sage: # needs sage.rings.number_field
                sage: x = polygen(ZZ, 'x')
                sage: K = NumberField(x^2 + 1, 's')
                sage: OK = K.ring_of_integers()
                sage: OK.integral_closure()
                Gaussian Integers generated by s in Number Field in s
                 with defining polynomial x^2 + 1
                sage: OK.integral_closure() == OK
                True

                sage: QQ.integral_closure() == QQ
                True
            """
            return self

        def is_noetherian(self) -> bool:
            r"""
            Return ``True`` since Dedekind domains are Noetherian.

            EXAMPLES:

            The integers, `\ZZ`, and rings of integers of number
            fields are Dedekind domains::

                sage: ZZ.is_noetherian()
                True
                sage: x = polygen(ZZ, 'x')
                sage: K = NumberField(x^2 + 1, 's')                                         # needs sage.rings.number_field
                sage: OK = K.ring_of_integers()                                             # needs sage.rings.number_field
                sage: OK.is_noetherian()                                                    # needs sage.rings.number_field
                True
                sage: QQ.is_noetherian()
                True
            """
            return True

    class ElementMethods:
        pass
